﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DynamicProperties.Tests
{
	[TestClass]
	public class ResetTests
	{
		DynamicProperty<string, int> testProperty1 = new DynamicProperty<string, int>("Test property 1");
		DynamicProperty<object, int> testProperty2 = new DynamicProperty<object, int>("Test property 2");

		[TestMethod]
		public void StringResetEmpty()
		{
			// reset should not throw exception even if object is not have any dynamic property assigned
			string obj1 = "ABCD";
			bool resetResult = Extender.Global.ResetObject(obj1);

			// reset should be unsuccessful (because there was no properties defined on 'obj1')
			Assert.IsFalse(resetResult);

		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ResetNullObject()
		{
			// should invoke exception
			Extender.Global.ResetObject(null);
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ResetNullObjectsProperty()
		{
			// should invoke exception
			Extender.Global.ResetProperty(null, testProperty1);
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ResetObjectsNullProperty()
		{
			// should invoke exception
			string obj1 = "ABC";
			DynamicProperty<object, int> propNull = null;
			Extender.Global.ResetProperty(obj1, propNull);
		}

		[TestMethod]
		public void StringResetObject()
		{
			// check if object reset will remove all defined properties from object instance
			int propertyValue1 = 123;
			int propertyValue2 = 321;

			string obj1 = "ABC";
			string obj2 = "DEF";

			// set value to obj1, obj2
			testProperty1.Set(obj1, propertyValue1);
			testProperty2.Set(obj1, propertyValue2);
			testProperty1.Set(obj2, propertyValue1);
			testProperty2.Set(obj2, propertyValue2);

			// reset obj1
			bool resetResult = Extender.Global.ResetObject(obj1);

			// reset should be successful (because there was some properties defined on 'obj1')
			Assert.IsTrue(resetResult);

			// values should be reseted in obj1
			Assert.AreEqual(0, testProperty1.Get(obj1)); // reseted
			Assert.AreEqual(0, testProperty2.Get(obj1)); // reseted
			Assert.AreEqual(propertyValue1, testProperty1.Get(obj2));
			Assert.AreEqual(propertyValue2, testProperty2.Get(obj2));
		}

		[TestMethod]
		public void StringResetProperty()
		{
			// check if property reset will remove specified property from object instance
			int propertyValue1 = 123;
			int propertyValue2 = 321;

			string obj1 = "ABC";
			string obj2 = "DEF";

			// set 2 properties on both obj1 and obj2
			testProperty1.Set(obj1, propertyValue1);
			testProperty2.Set(obj1, propertyValue2);
			testProperty1.Set(obj2, propertyValue1);
			testProperty2.Set(obj2, propertyValue2);

			// reset property on obj1
			bool resetResult = Extender.Global.ResetProperty(obj1, testProperty2);

			// reset should be successful (because there was some properties defined on 'obj1')
			Assert.IsTrue(resetResult);

			// values should be reseted in obj1 only on test property 2
			Assert.AreEqual(propertyValue1, testProperty1.Get(obj1));
			Assert.AreEqual(0, testProperty2.Get(obj1)); // reseted
			Assert.AreEqual(propertyValue1, testProperty1.Get(obj2));
			Assert.AreEqual(propertyValue2, testProperty2.Get(obj2));
		}

		[TestMethod]
		public void StringResetEmptyProperty()
		{
			string obj1 = "ABCEFG";

			// reset property on obj1
			bool resetResult = Extender.Global.ResetProperty(obj1, testProperty1);

			// reset should be unsuccessful (because property 'testProperty1' was not defined on 'obj1')
			Assert.IsFalse(resetResult);

			// value should be reseted in obj1
			Assert.AreEqual(0, testProperty1.Get(obj1)); // reseted
		}
	}
}
